Skip to content

프로필 생성 플로우 구현#102

Merged
moondev03 merged 35 commits into
developfrom
feat/#99-프로필-생성-화면-구현
Apr 20, 2026

Hidden character warning

The head ref may contain hidden characters: "feat/#99-\ud504\ub85c\ud544-\uc0dd\uc131-\ud654\uba74-\uad6c\ud604"
Merged

프로필 생성 플로우 구현#102
moondev03 merged 35 commits into
developfrom
feat/#99-프로필-생성-화면-구현

Conversation

@moondev03

@moondev03 moondev03 commented Apr 16, 2026

Copy link
Copy Markdown
Member

📌 작업 내용

로그인 이후 온보딩 흐름에 프로필 생성 단계를 연결하고, 프로필 생성/편집 화면 및 관련 도메인 계층을 추가했습니다.
함께 My 피처 모듈을 신설해 하단 탭의 프로필 진입점을 My로 정리했습니다.

로그인/약관 동의 이후 내비게이션 흐름 정리

  • 로그인 성공 후 후속 분기용 UiEffect 추가
  • 약관 동의 완료 시 홈 이동 대신 프로필 생성 화면으로 이동하도록 변경
  • ProfileNavKeyCreate / Edit로 분리

프로필 생성/편집 화면 구현

  • 프로필 이미지 편집 UI 추가
  • Android Photo Picker 연동으로 프로필 이미지 선택 지원
  • 닉네임 입력 필드 및 검증 상태별 helper message 추가
  • 닉네임 입력값 debounce 후 중복 검사 수행
  • 생성/편집 상태에 따라 상단바 타이틀 및 완료 버튼 활성화 조건 분리
  • 실패 상황에 대한 snackbar 메시지 처리 추가

프로필 관련 도메인/데이터 계층 추가

  • User, Nickname 모델 추가
  • FetchUserInfoUseCase, ValidateNicknameUseCase 추가
  • UserRepository 구현 및 Hilt 바인딩 추가
  • 닉네임 포맷 검증 및 중복 검사 흐름 구성

My 피처 모듈 추가

  • feature:my:api, feature:my:impl 신설
  • 하단 탭의 기존 Profile 진입점을 My로 교체

UI/인프라 보완

  • advancedImePadding 추가로 키보드 대응 개선
  • PrezelAvatar, PrezelTextField 정렬/기본 스타일 보정
  • PrezelAsyncImage 에러 로깅 추가
  • core-domain 모듈 및 관련 의존성/설정 추가

🧩 관련 이슈


📸 스크린샷

Screen_recording_20260416_231829.mp4

📢 참고사항

  • 현재 로그인 후 프로필 생성 완료 여부 확인 로직은 임시값으로 동작합니다.
  • 현재 프로필 제출은 실제 API 연동 전 단계로, 완료 버튼 클릭 시 임시로 홈으로 이동합니다.
  • UserRepositoryImpl의 유저 정보/닉네임 중복 검사는 테스트용 mock 구현입니다.

Summary by CodeRabbit

릴리스 노트

  • New Features

    • 프로필 생성·편집 화면 추가(닉네임 검사, 프로필 이미지 선택/편집 포함)
    • 새 ‘내 정보(My)’ 화면/탭 및 관련 내비게이션 추가
    • 도메인 모델 및 유스케이스(User, Nickname, 사용자 조회/검증) 추가
  • UI/UX 개선

    • 입력 감지/디바운스 단축으로 닉네임 반응성 향상
    • 키보드(IME) 처리 및 레이아웃 패딩 개선
    • 아바타 기본 크기·아이콘 스타일 및 이미지 로딩 오류 로깅 개선
  • Chores

    • 빌드/모듈 구성 업데이트 및 의존성 정리

`My` 피처를 위한 API 및 Implementation 모듈을 신규 생성하고, 메인 하단 탭 내비게이션에 추가하였습니다.

* **feat: My 피처 모듈 추가**
    * `:feature:my:api` 및 `:feature:my:impl` 모듈 생성 및 프로젝트 설정(`settings.gradle.kts`, `app/build.gradle.kts`) 반영
    * `MyNavKey`: 내비게이션을 위한 직렬화 가능한 데이터 객체 정의
    * `MyScreen`, `MyViewModel`, `MyUiState`: 기본적인 UI 컴포넌트 및 상태 관리 로직 구현
    * `MyEntryBuilder`: Hilt와 Navigation3를 이용한 화면 진입점 등록 및 의존성 주입 설정

* **feat: 메인 내비게이션에 My 탭 추가**
    * `TopLevelNavItem`: 하단 네비게이션 아이템 목록(`MAIN_NAV_ITEMS`)에 `MyNavKey` 추가
    * `strings.xml`: 하단 탭 표시를 위한 리소스(`bottom_nav_my`) 추가
`PrezelTextField`의 `innerTextField`와 `placeholder`를 포함하는 `Box` 컴포저블에 `contentAlignment = Alignment.CenterStart` 속성을 추가하여 내부 콘텐츠가 수직 중앙 및 시작 지점에 올바르게 정렬되도록 수정했습니다.
빈 디렉토리 구조를 유지하기 위해 `core:model` 및 `core:domain` 모듈의 테스트 경로에 `.gitkeep` 파일을 추가했습니다.
`core:model` 모듈에 사용자 정보를 관리하기 위한 `User` 데이터 모델을 추가했습니다.

*   `User`: id, email, nickname, profileImage, isRegistered 필드를 포함하는 사용자 데이터 클래스 정의
*   `ProfileImage`: 이미지 URL 및 기본 이미지 여부(`isDefault`)를 포함하는 하위 데이터 클래스 정의
키보드가 올라올 때 레이아웃의 전역 위치를 계산하여 불필요한 공백 없이 IME 패딩을 적용하는 `advancedImePadding` 확장 함수를 추가했습니다.

* `onGloballyPositioned`를 통해 루트 좌표계 대비 현재 컴포넌트의 하단 위치를 계산
* 계산된 하단 여백만큼 `consumeWindowInsets`를 적용하여 중복 패딩 방지
* `imePadding()`을 결합하여 키보드 활성화 시 동적인 패딩 조정 지원
`feature:login:impl` 모듈의 `build.gradle.kts`에 `kotlinx-serialization` 플러그인을 추가하였습니다.
`AndroidManifest.xml` 내 `MainActivity` 설정에 `android:windowSoftInputMode="adjustResize"` 속성을 추가하였습니다. 이를 통해 소프트 키보드가 나타날 때 레이아웃이 가려지지 않고 적절히 조정되도록 개선했습니다.
* feat: 프로필 이미지 변경 및 사진 선택 기능 추가

프로필 화면에서 이미지를 변경하거나 기본 이미지로 초기화할 수 있는 기능을 구현했습니다.

*   `ProfileViewModel`: `OnProfileImageChanged` 인텐트 처리 로직 추가 및 이미지 URL에 따른 `isDefault` 상태 관리
*   `ProfileScreen`: `ActivityResultContracts.PickVisualMedia`를 사용하여 시스템 사진 선택기 연동
*   `Avatar`: 프로필 이미지 클릭 시 사진 선택기를 띄우거나 이미지를 제거(기본 이미지로 변경)하는 로직 구현
*   프로필 이미지 우측 하단에 상태에 따라 회전하는 추가/삭제 아이콘 버튼 적용

* refactor: 프로필 UI 상태 및 네비게이션 구조 개선

프로필 상태 관리 모델을 보완하고 관련 컴포넌트 구조를 정리했습니다.

*   `ProfileUiState`: `profileImage` 필드를 추가하고, 기존 `isPrimaryActionEnabled`를 `submitButtonEnabled`로 명칭 변경
*   `ProfileNavKey.Edit`: 프로필 편집 시 기본 이미지 여부를 판단하기 위한 `isDefault` 파라미터 추가
*   `ProfileEntryBuilder`: 네비게이션 시 전달받은 `profileUrl`과 `isDefault` 정보를 초기 상태에 반영하도록 수정
*   `ProfileScreen`: 내부 레이아웃 로직을 `ProfileScreenContent`로 분리하여 가독성 개선 및 `advancedImePadding` 적용
*   `PrezelTextField`: 키보드 타입을 `Text`로 명시하고 불필요한 공백 제거 로직 유지

* style: 문자열 리소스 추가 및 정리

*   `feature_profile_impl_profile_image_content_description` 리소스 추가
*   `strings.xml` 내 리소스 간격 조정 및 정렬
`User` 데이터 모델 내 `nickname` 프로퍼티의 타입을 기존 커스텀 클래스인 `Nickname`에서 기본 타입인 `String`으로 변경하였습니다.
* refactor: PrezelAsyncImage 이미지 로드 실패 시 에러 로깅 로직 추가

이미지 로드 중 에러가 발생할 경우, 기존 `onError` 콜백 호출과 더불어 `Timber.e`를 통해 예외 상황을 로그로 기록하도록 개선하였습니다.

* chore: core:designsystem 모듈에 Timber 의존성 추가

로깅 라이브러리 사용을 위해 `build.gradle.kts`에 `timber` 의존성을 추가하였습니다.
* build: Feature 구현 모듈 공통 의존성에 Timber 추가

`AndroidFeatureImplConventionPlugin`에 `timber` 라이브러리 의존성을 추가하여, 해당 플러그인을 사용하는 모든 Feature 구현 모듈에서 로깅 라이브러리를 사용할 수 있도록 개선했습니다.
유저 정보 조회를 위한 UseCase를 추가하고, 캐싱 로직이 포함된 Repository 구현체를 업데이트했습니다.
* **refactor: ProfileViewModel 내 프로필 제출 활성화 조건 변경**
    * `submitProfile` 함수에서 버튼 활성화 여부를 단순히 닉네임 유효성 검사 결과(`NicknameValidationState.Available`)만 체크하던 방식에서, 상태 객체의 `submitButtonEnabled` 프로퍼티를 확인하도록 수정했습니다.
    * 프로필 수정 API 호출을 위한 주석 처리된 가이드 코드를 추가했습니다.

* **feat: ProfileUiEffect 내 뒤로가기 액션 추가 및 처리**
    * `ProfileUiEffect` 인터페이스에 `OnBack` 오브젝트를 추가했습니다.
    * `ProfileScreen`에서 `OnBack` 이펙트 수신 시 `onBack()` 콜백을 호출하도록 처리 로직을 추가했습니다.
`ProfileScreen`의 가독성과 유지보수성을 높이기 위해 내부 UI 로직을 별도 컴포저블로 분리하고 코드 구조를 정리했습니다.
`checkNicknameDuplication` 메서드 내의 `TODO` 주석을 `todo`로 변경하였습니다.
`ProfileUiState`의 상태 판단 로직을 구체화하고, 인터페이스 상속 구조를 정리하여 코드의 일관성을 높였습니다.
닉네임 입력 상태에 따른 검증 상태(NicknameValidationState) 할당 로직을 세분화하고 불필요한 체크를 제거했습니다.

*   `onNicknameChanged`: 닉네임이 비어있는 경우, 기존 닉네임 유무에 따라 `TooShort` 또는 `Unchecked` 상태를 할당하도록 수정했습니다.
*   `validateNickname`: 메서드 진입 시 닉네임 빈 값 체크를 단순화하고 중복된 상태 업데이트 로직을 제거했습니다.
@moondev03 moondev03 requested a review from HamBeomJoon as a code owner April 16, 2026 14:24
@moondev03 moondev03 linked an issue Apr 16, 2026 that may be closed by this pull request
@moondev03 moondev03 self-assigned this Apr 16, 2026
@coderabbitai

coderabbitai Bot commented Apr 16, 2026

Copy link
Copy Markdown
Contributor

Caution

Review failed

Pull request was closed or merged during review

📝 Walkthrough

Walkthrough

새 기능 모듈 My 추가, 프로필 생성/편집 화면 전면 구현, 도메인·데이터 계층(모델·닉네임 검증·레포지토리·유스케이스) 추가, 로그인 네비게이션 분기 변경, 디자인시스템·빌드 설정 및 의존성/네비게이션 맵 업데이트를 도입했습니다.

Changes

Cohort / File(s) Summary
My 기능 모듈
Prezel/feature/my/api/build.gradle.kts, Prezel/feature/my/api/src/main/java/.../MyNavKey.kt, Prezel/feature/my/api/*, Prezel/feature/my/impl/build.gradle.kts, Prezel/feature/my/impl/src/main/java/.../MyScreen.kt, Prezel/feature/my/impl/src/main/java/.../MyViewModel.kt, Prezel/feature/my/impl/src/main/java/.../MyUiState.kt, Prezel/feature/my/impl/src/main/java/.../MyEntryBuilder.kt, Prezel/feature/my/impl/src/main/res/values/strings.xml, Prezel/feature/my/*/proguard*.pro
새로운 feature/my 모듈 추가: API 내 MyNavKey(Serializable), 구현 모듈에 MyScreen, MyViewModel, UI 상태, 네비게이션 엔트리 및 빈 리소스/프로가드/consumer-rules 파일 추가.
프로필 기능 구현(대규모)
Prezel/feature/profile/api/ProfileNavKey.kt, Prezel/feature/profile/impl/src/main/java/.../ProfileScreen.kt, .../ProfileViewModel.kt, .../contract/*, .../component/*, .../model/*, .../navigation/ProfileEntryBuilder.kt, Prezel/feature/profile/impl/src/main/res/values/strings.xml
ProfileNavKey를 sealed variants(Create/Edit)로 변경하고, 프로필 생성/편집 UI(컴포넌트: 이미지 에디터, 닉네임 필드), UI 상태/의도/효과/메시지, ViewModel(유스케이스 연동·닉네임 디바운스·검증), 네비게이션 엔트리 분기 및 문자열 리소스 추가.
핵심 도메인·데이터·모델 추가
Prezel/core/domain/build.gradle.kts, Prezel/core/domain/src/main/kotlin/.../repository/profile/UserRepository.kt, .../usecase/user/FetchUserInfoUseCase.kt, .../usecase/user/ValidateNicknameUseCase.kt, Prezel/core/data/build.gradle.kts, Prezel/core/data/src/main/java/.../di/RepositoryModule.kt, Prezel/core/data/src/main/java/.../repository/UserRepositoryImpl.kt, Prezel/core/model/src/main/java/.../profile/User.kt, Prezel/core/model/src/main/java/.../profile/Nickname.kt
도메인 레이어에 UserRepository 인터페이스와 유스케이스(FetchUserInfo, ValidateNickname) 추가, 모델로 User/Nickname 도입, core/data에 UserRepositoryImpl 구현 및 Hilt 바인딩 추가.
로그인 흐름 변경
Prezel/feature/login/impl/build.gradle.kts, Prezel/feature/login/impl/src/main/java/.../landing/LoginScreen.kt, .../LoginViewModel.kt, .../contract/LoginUiEffect.kt, .../navigation/LoginEntryBuilder.kt, .../terms/TermsScreen.kt, .../terms/TermsViewModel.kt, .../terms/contract/TermsUiEffect.kt
로그인 성공 후 사용자 정보 조회로 홈 또는 프로필(생성) 분기 추가: NavigateToHome 효과와 NavigateToProfile 효과를 도입하고, 화면 서명 및 엔트리 빌더에서 대응 콜백 연결로 네비게이션 흐름 변경.
디자인시스템·UI 조정
Prezel/core/designsystem/build.gradle.kts, Prezel/core/designsystem/src/main/java/.../component/PrezelAsyncImage.kt, .../PrezelAvatar.kt, .../textfield/PrezelTextField.kt, .../textfield/PrezelTextFieldState.kt, Prezel/core/ui/src/main/java/.../AdvancedImePadding.kt
Timber 의존성 추가 및 AsyncImage 오류 로그 추가, PrezelAvatar 기본 크기·아이콘 색상 변경, 텍스트필드 내부 정렬 추가·idleMillis 단축, advancedImePadding Modifier 추가.
앱 모듈·네비게이션 변경
Prezel/app/build.gradle.kts, Prezel/app/src/main/AndroidManifest.xml, Prezel/app/src/main/java/com/team/prezel/navigation/TopLevelNavItem.kt
app 의존성에서 featureProfileApi 제거하고 featureMyApi/featureMyImpl 추가, MainActivity에 windowSoftInputMode="adjustResize" 추가, TopLevelNavItem에서 ProfileNavKeyMyNavKey로 교체(탑레벨 항목 변경).
빌드 설정·버전 카탈로그·플러그인
Prezel/build-logic/convention/src/main/java/.../AndroidFeatureImplConventionPlugin.kt, Prezel/gradle/libs.versions.toml, Prezel/settings.gradle.kts, Prezel/core/domain/.gitignore
빌드 로직에 Timber 라이브러리 추가, 버전 카탈로그에 javax.inject 항목 추가, settings에 :core:domain, :feature:my:api, :feature:my:impl 등록, core/domain/.gitignore에 /build 추가.
기타 소규모 변경
여러 모듈의 build.gradle.kts (feature/profile/impl, feature/login/impl 등) 및 리소스/프로가드 빈 파일들
여러 모듈의 Gradle 설정(의존성/플러그인) 업데이트 및 빈 리소스/consumer/proguard 파일 추가.

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed 제목은 PR의 주요 변경 사항인 프로필 생성 플로우 구현을 명확하게 요약하며, 간결하고 구체적입니다.
Description check ✅ Passed 설명은 템플릿의 모든 필수 섹션(작업 내용, 관련 이슈, 스크린샷)을 포함하며, 각 섹션이 충실하게 작성되었습니다.
Linked Issues check ✅ Passed PR은 #99의 프로필 사진 업로드, 닉네임 설정, 온보딩 흐름 연결, 생성/편집 상태 분리 등 모든 주요 요구사항을 구현했습니다.
Out of Scope Changes check ✅ Passed My 피처 모듈 추가, UI 컴포넌트 보정, 도메인/데이터 계층 추가 등은 모두 프로필 생성 플로우 구현의 필수 요소로서 범위 내입니다.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@moondev03 moondev03 added the ✨ feat 새로운 기능 추가 또는 기존 기능 확장 label Apr 16, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 8

🧹 Nitpick comments (4)
Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/PrezelAvatar.kt (1)

33-33: 디자인시스템 기본 크기 변경은 호출부 명시로 분리하는 편이 안전합니다.

기본값을 REGULAR로 바꾸면 size를 넘기지 않는 모든 호출이 120dp로 바뀝니다. 특정 화면 의도라면 해당 호출부에서만 size = PrezelAvatarSize.REGULAR를 명시하고, 컴포넌트 기본값은 유지하는 구성이 회귀를 줄입니다.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/PrezelAvatar.kt`
at line 33, The component default was changed to PrezelAvatarSize.REGULAR which
will silently enlarge every caller that omitted size; revert the parameter
default in the PrezelAvatar constructor signature from PrezelAvatarSize.REGULAR
back to the original smaller default (e.g. PrezelAvatarSize.SMALL) so existing
callers keep their intended size, and for screens that need the larger 120dp
explicitly update the call sites to pass size = PrezelAvatarSize.REGULAR; update
references to PrezelAvatar and PrezelAvatarSize accordingly.
Prezel/feature/profile/impl/src/main/java/com/team/prezel/feature/profile/impl/navigation/ProfileEntryBuilder.kt (1)

16-32: Create/Edit 엔트리 본문 중복은 공통화해두는 편이 안전합니다.

Line 16-32에서 ProfileScreen 호출 블록이 동일하므로 공통 함수(또는 공통 람다)로 추출하면 향후 한쪽만 수정되는 드리프트를 줄일 수 있습니다.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@Prezel/feature/profile/impl/src/main/java/com/team/prezel/feature/profile/impl/navigation/ProfileEntryBuilder.kt`
around lines 16 - 32, Extract the duplicated ProfileScreen construction used in
entry<ProfileNavKey.Create> and entry<ProfileNavKey.Edit> into a single reusable
function or lambda (e.g., a private function that takes the LocalNavigator or
returns the composable content) and call that from both entries; move the
LocalNavigator.current retrieval into the shared function or accept it as a
parameter so navigateToHome and onBack closures are created once and reused by
both entry<ProfileNavKey.Create> and entry<ProfileNavKey.Edit> (keep symbols
ProfileScreen, LocalNavigator.current, navigateToHome, onBack and the two
entry<> declarations as the call sites).
Prezel/feature/profile/impl/src/main/java/com/team/prezel/feature/profile/impl/ProfileScreen.kt (2)

99-116: Loading 상태에 대한 UI 처리 부재

uiStateLoading일 때 fetchedStatenull이 되어 모든 값이 기본값(빈 문자열, true 등)으로 처리됩니다. 로딩 중임을 사용자에게 표시하는 UI(스피너, 스켈레톤 등)가 있으면 UX가 개선될 수 있습니다.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@Prezel/feature/profile/impl/src/main/java/com/team/prezel/feature/profile/impl/ProfileScreen.kt`
around lines 99 - 116, 현재 ProfileScreen에서 uiState가 Loading일 때 fetchedState가
null로 처리되어 빈 값이 화면에 렌더링됩니다; ProfileScreen에서 uiState (ProfileUiState) 를 분기해
ProfileUiState.Loading일 경우 스피너 또는 스켈레톤을 렌더하도록 추가하고, 기존 ProfileScreenContent 호출은
ProfileUiState.Fetched인 경우에만 fetchedState 값을 전달하도록 변경하세요; 관련 심볼: ProfileScreen,
ProfileUiState, fetchedState, ProfileScreenContent, ProfileScreenTopAppBar —
Loading 분기에서 적절한 로딩 컴포저블을 표시하거나 ProfileScreenContent에 isLoading 플래그를 전달해 내부에서 로딩
UI를 보여주게 구현하면 됩니다.

53-69: Effect 수집과 Intent 전송 분리 고려

현재 LaunchedEffect(Unit) 내에서 FetchData Intent 전송과 uiEffect 수집을 함께 처리하고 있습니다. 이 패턴은 동작하지만, 두 관심사를 분리하면 가독성이 향상됩니다.

♻️ 제안하는 리팩토링
     LaunchedEffect(Unit) {
         viewModel.onIntent(ProfileUiIntent.FetchData)
+    }
 
+    LaunchedEffect(Unit) {
         viewModel.uiEffect.collect { effect ->
             when (effect) {
                 ProfileUiEffect.NavigateToHome -> navigateToHome()
                 ProfileUiEffect.OnBack -> onBack()
                 is ProfileUiEffect.ShowMessage -> {
                     val resId = when (effect.message) {
                         ProfileUiMessage.CHECK_NICKNAME_FAILED -> R.string.feature_profile_impl_check_nickname_failed_message
                         ProfileUiMessage.FETCH_USER_INFO_FAILED -> R.string.feature_profile_impl_fetch_user_info_failed_message
                     }
                     snackbarHostState.showPrezelSnackbar(message = resources.getString(resId))
                 }
             }
         }
     }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@Prezel/feature/profile/impl/src/main/java/com/team/prezel/feature/profile/impl/ProfileScreen.kt`
around lines 53 - 69, Split the current single LaunchedEffect into two focused
effects: one LaunchedEffect(Unit) that only dispatches
viewModel.onIntent(ProfileUiIntent.FetchData), and a separate
LaunchedEffect(Unit) (or LaunchedEffect(viewModel) as appropriate) that collects
viewModel.uiEffect.collect and handles ProfileUiEffect cases (NavigateToHome,
OnBack, ShowMessage -> resolve ProfileUiMessage to resId and call
snackbarHostState.showPrezelSnackbar). This separates intent sending from effect
collection (improves readability) while keeping the same handlers
(ProfileUiEffect, ProfileUiMessage, snackbarHostState.showPrezelSnackbar,
navigateToHome, onBack).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@Prezel/build-logic/convention/src/main/java/com/team/prezel/buildlogic/convention/plugin/AndroidFeatureImplConventionPlugin.kt`:
- Line 28: Remove the Timber dependency line in
AndroidFeatureImplConventionPlugin.kt (the
"implementation"(libs.findLibrary("timber").get()) entry) from the shared
convention and instead add an implementation dependency for Timber in the
profile feature's build.gradle.kts (the profile module's implementation
configuration). This keeps Timber only in the ProfileImpl module and prevents
other feature-impl modules (history, home, login, my, splash) from getting an
unnecessary dependency.

In `@Prezel/core/ui/src/main/java/com/team/prezel/core/ui/AdvancedImePadding.kt`:
- Around line 21-22: The compute for consumePadding in AdvancedImePadding.kt is
wrong: replace coordinates.positionInWindow() with coordinates.positionInRoot()
to use root-relative coordinates, and apply coerceAtLeast(0) to the entire
subtraction result (i.e., (rootSize.height - (positionInRoot().y +
size.height)).toInt().coerceAtLeast(0)) so negative paddings are clamped; update
the identical calculation at the other occurrence (the second consumePadding
usage) to the same pattern referencing findRootCoordinates(), positionInRoot(),
size, and coerceAtLeast.

In
`@Prezel/feature/login/impl/src/main/java/com/team/prezel/feature/login/impl/landing/LoginViewModel.kt`:
- Around line 58-63: In fetchMyInfo() the local flag isProfileCreateComplete is
hardcoded true which forces NavigateToHome; change this to use the actual user
registration/profile-completion value (or at minimum default to false) instead
of true so new users can reach the profile creation flow—update the logic inside
LoginViewModel.fetchMyInfo() to read the real completion state (or set
isProfileCreateComplete = false) and then call
sendEffect(LoginUiEffect.NavigateToHome) or
sendEffect(LoginUiEffect.NavigateToTerms) based on that value.

In
`@Prezel/feature/my/impl/src/main/java/com/team/prezel/feature/my/impl/MyScreen.kt`:
- Line 16: The hardcoded Text("My") in MyScreen should be replaced with a string
resource; change the Text call to use stringResource(R.string.my_title) (import
androidx.compose.ui.res.stringResource) so the UI text comes from resources, and
add the key my_title with value "My" to your strings.xml resource file.

In
`@Prezel/feature/my/impl/src/main/java/com/team/prezel/feature/my/impl/MyUiState.kt`:
- Around line 3-7: MyUiState currently only defines Loading and LoadFailed so it
cannot represent a successful (loaded) state; add a Success variant to the
sealed interface (e.g., data class Success(val data: <payloadType>) : MyUiState)
so MyViewModel/MyScreen can switch on MyUiState for the loaded content instead
of using separate flags; update any code referencing MyUiState to handle
Loading, Success and LoadFailed accordingly and choose an appropriate payload
type name for your feature's data.

In
`@Prezel/feature/profile/impl/src/main/java/com/team/prezel/feature/profile/impl/contract/ProfileUiState.kt`:
- Around line 55-57: The current submitButtonEnabled logic allows submission
when only profileImage changed even if nickname is invalid; change it so that if
nickname was modified (nickname != originalNickname) the button is enabled only
when nicknameValidation == NicknameValidationState.Available, otherwise
(nickname unchanged) enable the button when profileImage !=
originalProfileImage; update the submitButtonEnabled computation (referencing
submitButtonEnabled, nickname, originalNickname, nicknameValidation,
NicknameValidationState.Available, profileImage, originalProfileImage) to
implement this conditional branching.

In
`@Prezel/feature/profile/impl/src/main/java/com/team/prezel/feature/profile/impl/ProfileViewModel.kt`:
- Around line 120-123: 현재 닉네임 검증 결과가 오래된 입력에 덮어쓰는 문제를 방지하려면 updateState 블록 안에서
fetchedState.updateProfile(...)을 호출하기 전에 검증 대상 닉네임이 현재 UI 상태의 nickname과 일치하는지
확인하도록 변경하세요; 즉, ProfileUiState.Fetched에서 가져온 fetchedState.nickname과
validationState(현재 변수명)의 검증 대상(예: validationState.input 또는
validationState.nickname)에 대해 equality 체크를 하고 다르면 기존 currentState를 반환하여 무시하도록
처리한 뒤, 같을 때만 fetchedState.updateProfile(nicknameValidation = validationState)을
호출하도록 수정하세요.
- Around line 133-150: submitProfile currently always sends
ProfileUiEffect.NavigateToHome even when editing; change it to branch on the
runtime type of fetchedState (ProfileUiState.Create vs ProfileUiState.Edit) and
send the appropriate effect (NavigateToHome for Create, OnBack for Edit) using
sendEffect, and when re-enabling the patchUserProfileUseCase callback ensure the
success handler uses the same branching logic (refer to submitProfile,
ProfileUiState.Fetched, ProfileUiState.Create, ProfileUiState.Edit,
ProfileUiEffect.NavigateToHome, ProfileUiEffect.OnBack, and sendEffect).

---

Nitpick comments:
In
`@Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/PrezelAvatar.kt`:
- Line 33: The component default was changed to PrezelAvatarSize.REGULAR which
will silently enlarge every caller that omitted size; revert the parameter
default in the PrezelAvatar constructor signature from PrezelAvatarSize.REGULAR
back to the original smaller default (e.g. PrezelAvatarSize.SMALL) so existing
callers keep their intended size, and for screens that need the larger 120dp
explicitly update the call sites to pass size = PrezelAvatarSize.REGULAR; update
references to PrezelAvatar and PrezelAvatarSize accordingly.

In
`@Prezel/feature/profile/impl/src/main/java/com/team/prezel/feature/profile/impl/navigation/ProfileEntryBuilder.kt`:
- Around line 16-32: Extract the duplicated ProfileScreen construction used in
entry<ProfileNavKey.Create> and entry<ProfileNavKey.Edit> into a single reusable
function or lambda (e.g., a private function that takes the LocalNavigator or
returns the composable content) and call that from both entries; move the
LocalNavigator.current retrieval into the shared function or accept it as a
parameter so navigateToHome and onBack closures are created once and reused by
both entry<ProfileNavKey.Create> and entry<ProfileNavKey.Edit> (keep symbols
ProfileScreen, LocalNavigator.current, navigateToHome, onBack and the two
entry<> declarations as the call sites).

In
`@Prezel/feature/profile/impl/src/main/java/com/team/prezel/feature/profile/impl/ProfileScreen.kt`:
- Around line 99-116: 현재 ProfileScreen에서 uiState가 Loading일 때 fetchedState가 null로
처리되어 빈 값이 화면에 렌더링됩니다; ProfileScreen에서 uiState (ProfileUiState) 를 분기해
ProfileUiState.Loading일 경우 스피너 또는 스켈레톤을 렌더하도록 추가하고, 기존 ProfileScreenContent 호출은
ProfileUiState.Fetched인 경우에만 fetchedState 값을 전달하도록 변경하세요; 관련 심볼: ProfileScreen,
ProfileUiState, fetchedState, ProfileScreenContent, ProfileScreenTopAppBar —
Loading 분기에서 적절한 로딩 컴포저블을 표시하거나 ProfileScreenContent에 isLoading 플래그를 전달해 내부에서 로딩
UI를 보여주게 구현하면 됩니다.
- Around line 53-69: Split the current single LaunchedEffect into two focused
effects: one LaunchedEffect(Unit) that only dispatches
viewModel.onIntent(ProfileUiIntent.FetchData), and a separate
LaunchedEffect(Unit) (or LaunchedEffect(viewModel) as appropriate) that collects
viewModel.uiEffect.collect and handles ProfileUiEffect cases (NavigateToHome,
OnBack, ShowMessage -> resolve ProfileUiMessage to resId and call
snackbarHostState.showPrezelSnackbar). This separates intent sending from effect
collection (improves readability) while keeping the same handlers
(ProfileUiEffect, ProfileUiMessage, snackbarHostState.showPrezelSnackbar,
navigateToHome, onBack).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 861a1677-897d-4458-a05c-1030c2d238e3

📥 Commits

Reviewing files that changed from the base of the PR and between 5cea85b and 6a4bf13.

📒 Files selected for processing (58)
  • Prezel/app/build.gradle.kts
  • Prezel/app/src/main/AndroidManifest.xml
  • Prezel/app/src/main/java/com/team/prezel/navigation/TopLevelNavItem.kt
  • Prezel/build-logic/convention/src/main/java/com/team/prezel/buildlogic/convention/plugin/AndroidFeatureImplConventionPlugin.kt
  • Prezel/core/data/build.gradle.kts
  • Prezel/core/data/src/main/java/com/team/prezel/core/data/di/RepositoryModule.kt
  • Prezel/core/data/src/main/java/com/team/prezel/core/data/repository/UserRepositoryImpl.kt
  • Prezel/core/designsystem/build.gradle.kts
  • Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/PrezelAsyncImage.kt
  • Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/PrezelAvatar.kt
  • Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/textfield/PrezelTextField.kt
  • Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/textfield/PrezelTextFieldState.kt
  • Prezel/core/domain/.gitignore
  • Prezel/core/domain/build.gradle.kts
  • Prezel/core/domain/src/main/kotlin/com/team/prezel/core/domain/repository/profile/UserRepository.kt
  • Prezel/core/domain/src/main/kotlin/com/team/prezel/core/domain/usecase/user/FetchUserInfoUseCase.kt
  • Prezel/core/domain/src/main/kotlin/com/team/prezel/core/domain/usecase/user/ValidateNicknameUseCase.kt
  • Prezel/core/domain/src/test/kotlin/com/team/prezel/core/domain/.gitkeep
  • Prezel/core/model/src/main/java/com/team/prezel/core/model/profile/Nickname.kt
  • Prezel/core/model/src/main/java/com/team/prezel/core/model/profile/User.kt
  • Prezel/core/model/src/test/java/com/team/prezel/core/.gitkeep
  • Prezel/core/ui/src/main/java/com/team/prezel/core/ui/AdvancedImePadding.kt
  • Prezel/feature/login/impl/build.gradle.kts
  • Prezel/feature/login/impl/src/main/java/com/team/prezel/feature/login/impl/landing/LoginScreen.kt
  • Prezel/feature/login/impl/src/main/java/com/team/prezel/feature/login/impl/landing/LoginViewModel.kt
  • Prezel/feature/login/impl/src/main/java/com/team/prezel/feature/login/impl/landing/contract/LoginUiEffect.kt
  • Prezel/feature/login/impl/src/main/java/com/team/prezel/feature/login/impl/navigation/LoginEntryBuilder.kt
  • Prezel/feature/login/impl/src/main/java/com/team/prezel/feature/login/impl/terms/TermsScreen.kt
  • Prezel/feature/login/impl/src/main/java/com/team/prezel/feature/login/impl/terms/TermsViewModel.kt
  • Prezel/feature/login/impl/src/main/java/com/team/prezel/feature/login/impl/terms/contract/TermsUiEffect.kt
  • Prezel/feature/my/api/build.gradle.kts
  • Prezel/feature/my/api/consumer-rules.pro
  • Prezel/feature/my/api/proguard-rules.pro
  • Prezel/feature/my/api/src/main/java/com/team/prezel/feature/my/api/MyNavKey.kt
  • Prezel/feature/my/impl/build.gradle.kts
  • Prezel/feature/my/impl/consumer-rules.pro
  • Prezel/feature/my/impl/proguard-rules.pro
  • Prezel/feature/my/impl/src/main/java/com/team/prezel/feature/my/impl/MyScreen.kt
  • Prezel/feature/my/impl/src/main/java/com/team/prezel/feature/my/impl/MyUiState.kt
  • Prezel/feature/my/impl/src/main/java/com/team/prezel/feature/my/impl/MyViewModel.kt
  • Prezel/feature/my/impl/src/main/java/com/team/prezel/feature/my/impl/navigation/MyEntryBuilder.kt
  • Prezel/feature/my/impl/src/main/res/values/strings.xml
  • Prezel/feature/profile/api/src/main/java/com/team/prezel/feature/profile/api/ProfileNavKey.kt
  • Prezel/feature/profile/impl/build.gradle.kts
  • Prezel/feature/profile/impl/src/main/java/com/team/prezel/feature/profile/impl/ProfileScreen.kt
  • Prezel/feature/profile/impl/src/main/java/com/team/prezel/feature/profile/impl/ProfileUiState.kt
  • Prezel/feature/profile/impl/src/main/java/com/team/prezel/feature/profile/impl/ProfileViewModel.kt
  • Prezel/feature/profile/impl/src/main/java/com/team/prezel/feature/profile/impl/component/NicknameTextField.kt
  • Prezel/feature/profile/impl/src/main/java/com/team/prezel/feature/profile/impl/component/ProfileImageEditor.kt
  • Prezel/feature/profile/impl/src/main/java/com/team/prezel/feature/profile/impl/component/ProfileScreenTopAppBar.kt
  • Prezel/feature/profile/impl/src/main/java/com/team/prezel/feature/profile/impl/contract/ProfileUiEffect.kt
  • Prezel/feature/profile/impl/src/main/java/com/team/prezel/feature/profile/impl/contract/ProfileUiIntent.kt
  • Prezel/feature/profile/impl/src/main/java/com/team/prezel/feature/profile/impl/contract/ProfileUiState.kt
  • Prezel/feature/profile/impl/src/main/java/com/team/prezel/feature/profile/impl/model/ProfileUiMessage.kt
  • Prezel/feature/profile/impl/src/main/java/com/team/prezel/feature/profile/impl/navigation/ProfileEntryBuilder.kt
  • Prezel/feature/profile/impl/src/main/res/values/strings.xml
  • Prezel/gradle/libs.versions.toml
  • Prezel/settings.gradle.kts
💤 Files with no reviewable changes (1)
  • Prezel/feature/profile/impl/src/main/java/com/team/prezel/feature/profile/impl/ProfileUiState.kt

Comment thread Prezel/core/ui/src/main/java/com/team/prezel/core/ui/AdvancedImePadding.kt Outdated
`advancedImePadding` 수정자 내에서 컴포넌트의 하단 위치를 계산할 때의 기준 좌표와 수치 변환 방식을 수정하였습니다.

*   `positionInWindow()` 대신 `positionInRoot()`를 사용하여 윈도우 기준이 아닌 루트 레이아웃 기준으로 좌표를 계산하도록 변경했습니다.
*   좌표 값 변환 시 `toInt()` 대신 `roundToInt()`를 적용하여 정확도를 개선하고 불필요한 `coerceAtLeast(0)` 호출을 정리했습니다.
`ProfileUiState.Fetched` 상태에서 프로필 수정 버튼(`submitButtonEnabled`)이 활성화되는 조건을 더 엄격하게 개선했습니다.

*   닉네임의 유효성 상태(`nicknameValidation`)가 `Available`인 경우를 필수 조건으로 설정하였습니다.
*   닉네임 또는 프로필 이미지 중 최소 하나라도 변경되었을 때만 버튼이 활성화되도록 로직을 수정했습니다. (기존에는 닉네임이 유효하지 않은 상태여도 프로필 이미지만 변경되면 버튼이 활성화될 수 있었던 문제를 해결)
`updateNicknameValidation` 함수에서 유효성 검사 결과가 현재 입력된 닉네임과 일치할 때만 상태를 업데이트하도록 방어 로직을 추가했습니다. 비동기 처리 과정에서 발생할 수 있는 상태 불일치 문제를 방지합니다.
`ProfileUiState`의 복잡한 인터페이스 구조를 단순화하고, 관련 도메인 모델의 위치를 재정의하여 가독성과 유지보수성을 높였습니다.

* **refactor: ProfileUiState 구조 단순화 및 통합**
    * 기존 `Fetched`, `Create`, `Edit`으로 나뉘어 있던 상태 구조를 `ProfileUiState.Content` 단일 데이터 클래스로 통합했습니다.
    * `isNewProfile` 여부를 상태 클래스 내부가 아닌 `ProfileScreen` 파라미터를 통해 외부에서 주입받도록 변경했습니다.
    * `canPhotoPickerLaunch()` 함수를 `shouldLaunchPhotoPicker` 프로퍼티로 변경하고 로직을 정리했습니다.
    * `User.toUiState()` 확장 함수 내에서 사용자 등록 여부(`isRegistered`)에 따라 초기 닉네임 검증 상태를 설정하도록 수정했습니다.

* **refactor: NicknameValidationState 위치 변경**
    * `ProfileUiState.kt` 내부에 정의되어 있던 `NicknameValidationState` enum 클래스를 별도 파일(`model/NicknameValidationState.kt`)로 분리했습니다.

* **refactor: ProfileViewModel 로직 수정**
    * 변경된 `ProfileUiState.Content` 구조에 맞춰 `handleNicknameChanged`, `handleProfileImageChanged` 등의 상태 업데이트 로직을 `copy` 기반으로 간소화했습니다.

* **style: ProfileScreen 및 Preview 코드 정리**
    * `ProfileScreen` 컴포저블에 `isNewProfile` 파라미터를 추가하여 상단 바 UI(`isCreate`) 결정 로직을 분리했습니다.
    * 중복되던 `EditProfileScreenPreview`를 제거하고 통합된 상태를 사용하는 `CreateProfileScreenPreview`로 정리했습니다.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

♻️ Duplicate comments (1)
Prezel/feature/profile/impl/src/main/java/com/team/prezel/feature/profile/impl/ProfileViewModel.kt (1)

134-151: ⚠️ Potential issue | 🟠 Major

편집 저장 후에도 항상 홈으로 이동합니다.

지금은 생성/편집 구분 없이 NavigateToHome만 보내고 있어서, ProfileNavKey.Edit로 들어온 경우도 저장 후 홈으로 튑니다. 현재 ProfileUiState.Content에는 모드 정보가 없으니, isNewProfile를 ViewModel 상태나 submit intent로 함께 넘겨서 effect를 분기해야 합니다.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@Prezel/feature/profile/impl/src/main/java/com/team/prezel/feature/profile/impl/ProfileViewModel.kt`
around lines 134 - 151, The submitProfile() always sends
ProfileUiEffect.NavigateToHome regardless of create/edit; add a mode flag (e.g.,
isNewProfile) to the ViewModel state or include it on the submit intent so
submitProfile() can branch: inside submitProfile(), read the mode from
ProfileUiState.Content (or the submit intent) and send
ProfileUiEffect.NavigateToHome when isNewProfile is true, otherwise send
ProfileUiEffect.OnBack for edit; update the ProfileUiState.Content (or the
submit flow) to carry that isNewProfile boolean and use that symbol in
submitProfile() to decide which effect to send.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@Prezel/feature/profile/impl/src/main/java/com/team/prezel/feature/profile/impl/ProfileScreen.kt`:
- Around line 76-85: The current onClickProfileImage handler only launches
photoPickerLauncher when uiState.shouldLaunchPhotoPicker is true and otherwise
calls viewModel.onIntent(ProfileUiIntent.OnProfileImageChanged(profileUrl = ""))
which deletes the image immediately; update this so tapping always opens the
photo picker instead of sending an empty URL (or split delete into a distinct
action), i.e., change the onClickProfileImage logic to always call
photoPickerLauncher.launch(PickVisualMediaRequest(...)) and move deletion to a
separate UI affordance (e.g., a dedicated delete button or long-press) that
dispatches ProfileUiIntent.OnProfileImageChanged(profileUrl = "") via
viewModel.onIntent.

In
`@Prezel/feature/profile/impl/src/main/java/com/team/prezel/feature/profile/impl/ProfileViewModel.kt`:
- Around line 53-60: On fetchUserInfo failure you only send an effect but never
update the UI state, leaving the screen stuck in Loading; in the onFailure block
of fetchUserInfoUseCase() call update the ViewModel state (via updateState) to
reflect a non-loading / error or retry-able state (e.g. set isLoading = false
and set an error flag/message or switch to a ProfileUiState.Error) and still
call
sendEffect(ProfileUiEffect.ShowMessage(ProfileUiMessage.FETCH_USER_INFO_FAILED));
update the onFailure branch to both send the effect and mutate the state so the
UI can render retry controls instead of an empty loading screen.

---

Duplicate comments:
In
`@Prezel/feature/profile/impl/src/main/java/com/team/prezel/feature/profile/impl/ProfileViewModel.kt`:
- Around line 134-151: The submitProfile() always sends
ProfileUiEffect.NavigateToHome regardless of create/edit; add a mode flag (e.g.,
isNewProfile) to the ViewModel state or include it on the submit intent so
submitProfile() can branch: inside submitProfile(), read the mode from
ProfileUiState.Content (or the submit intent) and send
ProfileUiEffect.NavigateToHome when isNewProfile is true, otherwise send
ProfileUiEffect.OnBack for edit; update the ProfileUiState.Content (or the
submit flow) to carry that isNewProfile boolean and use that symbol in
submitProfile() to decide which effect to send.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: dc5bc693-8687-48e2-9ec7-238613b888d0

📥 Commits

Reviewing files that changed from the base of the PR and between 6a4bf13 and c539b69.

📒 Files selected for processing (6)
  • Prezel/core/ui/src/main/java/com/team/prezel/core/ui/AdvancedImePadding.kt
  • Prezel/feature/profile/impl/src/main/java/com/team/prezel/feature/profile/impl/ProfileScreen.kt
  • Prezel/feature/profile/impl/src/main/java/com/team/prezel/feature/profile/impl/ProfileViewModel.kt
  • Prezel/feature/profile/impl/src/main/java/com/team/prezel/feature/profile/impl/contract/ProfileUiState.kt
  • Prezel/feature/profile/impl/src/main/java/com/team/prezel/feature/profile/impl/model/NicknameValidationState.kt
  • Prezel/feature/profile/impl/src/main/java/com/team/prezel/feature/profile/impl/navigation/ProfileEntryBuilder.kt
✅ Files skipped from review due to trivial changes (1)
  • Prezel/feature/profile/impl/src/main/java/com/team/prezel/feature/profile/impl/model/NicknameValidationState.kt
🚧 Files skipped from review as they are similar to previous changes (2)
  • Prezel/feature/profile/impl/src/main/java/com/team/prezel/feature/profile/impl/navigation/ProfileEntryBuilder.kt
  • Prezel/core/ui/src/main/java/com/team/prezel/core/ui/AdvancedImePadding.kt

`Nickname.Companion.create(nickname)` 형태의 명시적 `Companion` 참조를 `Nickname.create(nickname)`으로 변경하여 코드를 간결하게 수정하였습니다.
* `feature_profile_impl_nickname_text_field_placeholder` 리소스의 내용을 "닉네임을 입력해 주세요"에서 "최대 10자까지 입력이 가능해요"로 변경하였습니다.
* 관련 리소스 영역의 주석을 `Helper Message`에서 `Nickname TextField`로 수정하였습니다.

@HamBeomJoon HamBeomJoon left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

고생하셨습니당

`ProfileUiIntent`의 명칭을 행위 중심의 직관적인 이름으로 변경하고, 이를 `ProfileViewModel` 및 `ProfileScreen`에 반영하였습니다.

* **refactor: ProfileUiIntent 파라미터 및 클래스 명칭 변경**
    * `OnNicknameChanged` -> `UpdateNickname`
    * `OnProfileImageChanged` -> `UpdateProfileImage`
    * `OnClickSubmit` -> `SubmitProfile`

* **refactor: ViewModel 및 UI 레이어 내 변경 사항 반영**
    * `ProfileViewModel`의 `onIntent` 핸들러 내 변경된 Intent 명칭 적용
    * `ProfileScreen`에서 `viewModel.onIntent` 호출 시 변경된 Intent 클래스 사용
@moondev03 moondev03 merged commit 4739f93 into develop Apr 20, 2026
1 of 2 checks passed
@moondev03 moondev03 deleted the feat/#99-프로필-생성-화면-구현 branch April 20, 2026 19:05
This was referenced May 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

✨ feat 새로운 기능 추가 또는 기존 기능 확장

Projects

None yet

Development

Successfully merging this pull request may close these issues.

프로필 생성 화면 구현

2 participants